home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / Found / ODUtils / Unused / ODDebug.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-16  |  11.1 KB  |  515 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        ODDebug.cpp
  3.  
  4.     Contains:    Useful debugging macros and functions.
  5.  
  6.     Owned by:    Jens Alfke
  7.  
  8.     Copyright:    © 1993 - 1995 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #ifndef _ODDEBUG_
  13. #include "ODDebug.h"
  14. #endif
  15.  
  16. #ifndef _EXCEPT_
  17. #include "Except.h"
  18. #endif
  19.  
  20. #ifndef _PLFMDEF_
  21. #include "PlfmDef.h"
  22. #endif
  23.  
  24. #ifndef _PASCLSTR_
  25. #include "PasclStr.h"
  26. #endif
  27.  
  28. #ifndef _PLFMDEF_
  29. #include "PlfmDef.h"
  30. #endif
  31.  
  32. #ifndef _EXCEPT_
  33. #include "Except.h"
  34. #endif
  35.  
  36. #ifndef _TEXTUTILS_
  37. #include "TextUtils.h"
  38. #endif
  39.  
  40. #ifndef _CRAWL_
  41. #include "Crawl.h"
  42. #endif
  43.  
  44. #ifndef _USERSRCM_
  45. #include "UseRsrcM.h"
  46. #endif
  47.  
  48. #ifndef _DLOGUTIL_
  49. #include "DlogUtil.h"
  50. #endif
  51.  
  52. #ifndef _UTILDEFS_
  53. #include "UtilDefs.h"
  54. #endif
  55.  
  56. #include <somobj.xh>
  57. #include <somcls.xh>
  58.  
  59. #include <stdio.h>
  60. #include <stdarg.h>
  61. #include <string.h>
  62.  
  63.  
  64. const ODSShort kOutputBufferSize = 400;
  65.  
  66. static somTD_SOMOutCharRoutine    *gOld_SOMOutCharRoutine;
  67. static somTD_SOMError            *gOld_SOMError;
  68.  
  69. // The output buffer is circular. We keep two indices, one for the start
  70. // of the most recent string and one for the end (the current input position.)
  71. static char gOutputBuffer[kOutputBufferSize];
  72. static ODSShort gOutputStart = 0;
  73. static ODSShort gOutputEnd   = 0;
  74.  
  75. static DebugOutputMode gOutputMode = kNoOutput;
  76.  
  77.  
  78. void BREAK( const char[] );
  79.  
  80. static short    gOutputFile = kODNULL;
  81.  
  82. //=====================================================================================
  83. // ODInitExceptions
  84. //=====================================================================================
  85.  
  86.  
  87. extern "C" {
  88.     static int OD_SOMOutCharRoutine( char c );
  89.     static void OD_SOMError( int error, corbastring filename, int linenum );
  90. }
  91.  
  92.  
  93. void
  94. ODInitExceptions( )
  95. {
  96.     gOld_SOMOutCharRoutine    = SOMOutCharRoutine;
  97.     gOld_SOMError            = SOMError;
  98.     SOMOutCharRoutine        = OD_SOMOutCharRoutine;
  99.     SOMError                = OD_SOMError;
  100. //    SOM_WarnLevel            = 1; // all, from somcdev.h
  101. }
  102.  
  103.  
  104. //=====================================================================================
  105. // Output routines
  106. //=====================================================================================
  107.  
  108.  
  109. #ifdef _PLATFORM_MACINTOSH_
  110.  
  111. #ifndef __STRINGS__
  112. #include <Strings.h>
  113. #endif
  114.  
  115.  
  116. static OSErr
  117. SendToDebugWindow( const char buffer[], short length )
  118. {
  119.     // Code adapted from API to "DebugWindow" app by Keith Ledbetter
  120.     AEAddressDesc    address;
  121.     AppleEvent        appleEvent, reply;
  122.     OSType            targetSig;
  123.     OSErr            err;
  124.  
  125.     targetSig = 'LdbW';
  126.     err= AECreateDesc( typeApplSignature, (Ptr)&targetSig, 
  127.                         sizeof(targetSig), &address );
  128.     if( !err ) {
  129.         err= AECreateAppleEvent( 'misc', 'dmsg', &address, kAutoGenerateReturnID,
  130.                                    kAnyTransactionID, &appleEvent );
  131.         AEDisposeDesc( &address );
  132.         if( !err ) {
  133.             err= AEPutParamPtr( &appleEvent, keyDirectObject, typeChar,
  134.                                  buffer, length );
  135.             if( !err ) {
  136.                 err= AESend( &appleEvent, &reply, 
  137.                          kAEWaitReply + kAENeverInteract,
  138.                          kAENormalPriority, 
  139.                          300,                                 // up to 5 second wait..
  140.                          kODNULL, kODNULL );
  141.                 AEDisposeDesc( &reply );
  142.             }
  143.             AEDisposeDesc( &appleEvent );
  144.         }
  145.     }
  146.     return err;
  147. }
  148.  
  149.  
  150. static short CreateNewOutputFile()
  151. {
  152.     static long    nextFilePrefixNum = 1;
  153.  
  154.     Str255            fileNameRootString = "\pstdout";
  155.     Size            fileNameRootLength = fileNameRootString[0];
  156.     Str255            numString;
  157.     Str255            fileNameString;
  158.     short            file = 0;
  159.  
  160.     CopyPascalString(fileNameString, fileNameRootString);
  161.  
  162.     OSErr err = Create(fileNameRootString, 0, 'MPS ', 'TEXT');
  163.     if (err)
  164.     {
  165.         while(err)
  166.         {
  167.             CopyPascalString(fileNameString, fileNameRootString);
  168.             NumToString(nextFilePrefixNum, numString);
  169.             // check for filename too long.
  170.             if (numString[0] + fileNameRootLength > 255)
  171.             {
  172.                 err = 1;
  173.                 break;
  174.             }
  175.             ConcatPascalStrings(fileNameString, numString);
  176.             err = Create(fileNameString, 0, 'MPS ', 'TEXT');
  177.             ++nextFilePrefixNum;
  178.             if (nextFilePrefixNum > 10000) // arbitrary infinite loop stopper.
  179.                 break;
  180.         }
  181.     }
  182.  
  183.     if (!err)
  184.     {
  185.         err = FSOpen(fileNameString, 0, &file);
  186.         if (err)
  187.             file = 0;
  188.     }
  189.  
  190.     return file;
  191. }
  192.  
  193.  
  194. static ODSShort
  195. ExtractBufferString( ODSShort start, ODSShort end, char output[] )
  196. {
  197.     ODSShort len = end-start;
  198.     if( len >= 0 )
  199.         ODBlockMove(gOutputBuffer+start, output, len);
  200.     else {
  201.         ODSShort len1 = kOutputBufferSize-start;
  202.         ODBlockMove(gOutputBuffer+start, output,len1);
  203.         ODBlockMove(gOutputBuffer, output+len1, end);
  204.         len += kOutputBufferSize;
  205.     }
  206.     output[len] = '\0';
  207.     return len;
  208. }
  209.  
  210.  
  211. static int
  212. OD_SOMOutCharRoutine( char c )
  213. {
  214.     if( c ==0x0A )                    // Convert Unix-style newline to Return
  215.         c = 0x0D;
  216.     
  217.     // Add to buffer, wrapping around:
  218.     gOutputBuffer[gOutputEnd++] = c;
  219.     if( gOutputEnd >= kOutputBufferSize )
  220.         gOutputEnd = 0;
  221.  
  222.     if( c == 0x0D )    {            // Dump buffer at end of line
  223.         if( gOutputMode == kWriteToDebugWindow
  224.                 || gOutputMode == kGenerateDebugStrs
  225.                 || gOutputMode == kWriteToFile)
  226.         {
  227.             // Convert latest output to string:
  228.             char output[kOutputBufferSize+1];
  229.             ODSShort len = ExtractBufferString(gOutputStart,gOutputEnd, output);
  230.                         
  231.             OSErr err = noErr;
  232.         
  233.             if (gOutputMode == kWriteToDebugWindow)
  234.                 err = SendToDebugWindow(output,len);
  235.             else if (gOutputMode == kGenerateDebugStrs)
  236.             {
  237.                 // Convert buffer to pascal string
  238.                 memmove(output + 1, output, len);
  239.                 output[0] = len<=255 ?len :255;
  240.                 DebugStr((StringPtr)output);
  241.             }
  242.             else if (gOutputMode == kWriteToFile)
  243.             {
  244.                 if (gOutputFile == NULL)
  245.                     gOutputFile = CreateNewOutputFile();
  246.                 if (gOutputFile)
  247.                 {
  248.                     long    bytesToWrite = len;
  249.                     err = FSWrite(gOutputFile, &bytesToWrite, output);
  250.                     if (!err && bytesToWrite != len)
  251.                         err = 1;
  252.                 }
  253.                 else
  254.                     err = 1;
  255.             }
  256.     
  257.             if( err )
  258.             {
  259.                 gOutputMode = kGenerateDebugStrs;
  260.                 DebugStr((StringPtr)"\pSOM Message Output: Error writing output -- reverting to DebugStr mode.");
  261.             }
  262.         }
  263.         
  264.         gOutputStart = gOutputEnd;        // "clear" buffer
  265.     }
  266.     
  267.     return 1;
  268. }
  269.  
  270.  
  271. #else /* if not _PLATFORM_MACINTOSH_: */
  272.  
  273.  
  274. static int
  275. OD_SOMOutCharRoutine( char c )
  276. {
  277.     if( gOutputMode == kWriteToFile )
  278.         return gOld_SOMOutCharRoutine(c);
  279.     else
  280.         return 1;
  281. }
  282.  
  283. #endif
  284.  
  285.  
  286. DebugOutputMode
  287. GetOutputMode( )
  288. {
  289.     return gOutputMode;
  290. }
  291.  
  292.  
  293. void
  294. SetOutputMode( DebugOutputMode mode )
  295. {
  296.     if( gOutputMode == kWriteToDebugWindow )
  297.         if( gOutputEnd != gOutputStart )
  298.             OD_SOMOutCharRoutine(0x0D);        // Flush buffer
  299.     gOutputMode = mode;
  300. }
  301.  
  302.  
  303. //=================================================================================== 
  304. // BREAK
  305. //=================================================================================== 
  306.  
  307. void
  308. BREAK( const char msg[] )
  309. {
  310.     somPrintf("%s\n",msg);
  311.     
  312. #ifdef _PLATFORM_MACINTOSH_
  313. #if ODDebug
  314.     // Now convert to Pascal string and call DebugStr:
  315.     Str255 pstr;
  316.     long len = strlen(msg);
  317.     pstr[0] = (len>255) ?255 :len;
  318.     for( int i=pstr[0]; i>0; i-- ) {
  319.         char c = msg[i-1];
  320.         if( c==';' ) c=':';        // ";" is bad in DebugStrs
  321.         pstr[i] = c;
  322.     }
  323.     DebugStr(pstr);
  324. #endif
  325. #endif
  326. }
  327.  
  328.  
  329. //=================================================================================== 
  330. // SOMError
  331. //=================================================================================== 
  332.  
  333. static ODBoolean IsOptionKeyDown()
  334. {
  335.     const ODUShort theKey = 0x3A;    // option key
  336.     unsigned char theKeys[16];
  337.     GetKeys((UInt32*)&theKeys);
  338.  
  339.     return ((theKeys[theKey >> 3] >> (theKey & 7)) & 1);
  340. }
  341.  
  342. static void
  343. OD_SOMError( int error, corbastring filename, int linenum )
  344. {
  345.     const char *kSeverityCode[10] =
  346.                 {"error","warning","message","error?","error?",
  347.                  "error template","error?","error?","error?","fatal error"};
  348.     int base = error / 10000;
  349.     int errno = (error - base*10000) / 10;
  350.     int severity = error % 10;
  351.     
  352.     char msg[kOutputBufferSize+3];
  353.     sprintf(msg, "SOM %s %d-%03d-%d (%s %d): Press G...",
  354.                         kSeverityCode[severity],base,errno,severity,
  355.                         filename,linenum);
  356.     
  357.     if( severity == SOM_Fatal ) {
  358.         somPrintf(msg);
  359.         CUsingLibraryResources r;
  360.         DialogPtr d = kODNULL; ODVolatile(d);
  361.         TRY{
  362.             InitCursor();
  363.             ::Alert(kSOMErrorAlertID,kODNULL);
  364.             if( IsOptionKeyDown() ) {
  365.                 d = ::GetNewDialog(kSOMErrorDlogID,kODNULL,(WindowPtr)-1L);
  366.                 SetDialogDefaultItem(d,ok);
  367.                 SetDialogTextStyle(d,kSOMErrorDlogFontInfo, smCurrentScript);
  368.                 
  369.                 // Copy the entire output buffer, not just the last line:
  370.                 ODSShort start = gOutputEnd;
  371.                 do{
  372.                     ++start;
  373.                     if( start >= kOutputBufferSize ) start=0;
  374.                 }while( start!=gOutputEnd && gOutputBuffer[start]=='\0' );
  375.                 strcpy(msg,"...");
  376.                 ODSShort len = ExtractBufferString(start,gOutputEnd, msg+3) +3;
  377.  
  378.                 short typ;
  379.                 Handle h;
  380.                 Rect box;
  381.                 ::GetDialogItem(d,kSOMErrorDlogTextItem, &typ,&h,&box);
  382.                 PtrToXHand(msg,h,len);
  383.                 
  384.             #if !ODDebug
  385.                 HideDialogItem(d,kSOMErrorDlogDebugButton);
  386.             #endif
  387.                 
  388.                 ShowWindow(d);
  389.                 SelectWindow(d);
  390.                 ODSShort item;
  391.                 ModalDialog(kODNULL,&item);
  392.                 
  393.             #if ODDebug
  394.                 if( item == kSOMErrorDlogDebugButton )
  395.                     Debugger();        // Have a look around...
  396.             #endif
  397.             }
  398.         }CATCH_ALL{
  399.             WARN("Caught error %d displaying SOM error dialog",ErrorCode());
  400.         }ENDTRY
  401.         if( d ) DisposeDialog(d);
  402.         
  403.     } else
  404.         BREAK(msg);                // Nonfatal error: just break
  405.  
  406.     gOld_SOMError(error,filename,linenum);
  407. }
  408.  
  409.  
  410. //=================================================================================== 
  411. // ASSERTION-FAILED
  412. //=================================================================================== 
  413.  
  414. #if ODDebug
  415.  
  416. void _AssertionFailed( char *cond, char *filename,
  417.                         ODError error, char *msg /*=NULL*/ )
  418. {
  419.     char where[300];
  420.     if( ! GetNameOfCaller(where) )
  421.         strcpy(where,filename);
  422.         
  423.     ODUnused(filename);
  424.     char dbg[256];
  425.     if( msg )
  426.         sprintf(dbg,"%s: %s ...NOT! At %s", msg,cond,where); 
  427.     else
  428.         sprintf(dbg,"%s ...NOT! At %s", cond,where); 
  429.     BREAK(dbg);
  430.     
  431.     if( error!=0 )
  432.         THROW(error, msg ?msg :"Assertion failed");
  433. }
  434.  
  435. #else /*not ODDebug*/
  436.  
  437. extern "C" void _AssertionFailed(  char *cond, char *filename,
  438.                         ODError error, char *msg );
  439. void _AssertionFailed( char *cond, char *filename,
  440.                         ODError error, char *msg )
  441. {
  442. }
  443.     
  444. #endif /*ODDebug*/
  445.     
  446.     
  447. //=================================================================================== 
  448. // WARN
  449. //=================================================================================== 
  450.  
  451. #if ODDebug
  452.  
  453. void _Warn( char *fmt, ... )
  454. {
  455.     char msg[512];
  456.     strcpy(msg, "ODWarning: ");
  457.     va_list args;
  458.     va_start(args,fmt);
  459.     vsprintf(msg+strlen(msg),fmt,args);
  460.     va_end(args);
  461.     
  462.     char caller[300];
  463.     if( GetNameOfCaller(caller) ) {
  464.         strcat(msg," (at ");
  465.         strcat(msg,caller);
  466.         strcat(msg,")");
  467.     }
  468.     
  469.     BREAK(msg);
  470. }
  471.     
  472. #else /*not ODDebug*/
  473.  
  474. extern "C" void _Warn(  char *fmt, ... );
  475. void _Warn(  char *fmt, ... )
  476. {
  477. }
  478.  
  479. #endif /*ODDebug*/
  480.     
  481. //==============================================================================
  482. // SAFE CAST
  483. //==============================================================================
  484.  
  485.  
  486. #if ODDebug
  487.  
  488. SOMObject*
  489. _Cast( SOMObject *obj, somClassDataStructure *clsdata, long majorversion, long minorversion )
  490. {
  491.     SOMClass *cls = (SOMClass*) somGetStaticClassReference(clsdata,majorversion,minorversion);
  492.     if( !somIsObj(obj) )
  493.         WARN("Can't cast: %p is not a SOM object",obj);
  494.     else if( !somIsObj(cls) )
  495.         WARN("Can't cast: %p is not a SOM class",cls);
  496.     else if( !obj->somIsA(cls) )
  497.         WARN("Can't cast: %p is an %s, not an %s",obj, obj->somGetClassName(), cls->somGetName());
  498.     else {
  499.         somReleaseClassReference(cls);
  500.         return obj;
  501.     }
  502.     somReleaseClassReference(cls);
  503.     THROW(kODErrAssertionFailed);
  504.     return NULL; /* keeps compiler quiet */
  505. }
  506.  
  507. #else /*not ODDebug*/
  508.  
  509. extern "C" void _Cast( );
  510. void _Cast( )
  511. {
  512. }
  513.     
  514. #endif /*ODDebug*/
  515.